package com.yutel.multher.reaper;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yutel.multher.reaper.domain.QueueList;
import com.yutel.multher.reaper.domain.ServerType;
import com.yutel.multher.reaper.domain.TaskData;
import com.yutel.multher.reaper.exception.ReaperException;
import com.yutel.multher.reaper.listener.OnAutoListener;
import com.yutel.multher.reaper.listener.OnDataListener;
import com.yutel.multher.reaper.listener.OnTaskListener;
import com.yutel.multher.reaper.task.AutarkicTask;
import com.yutel.multher.reaper.task.ParallelTask;
import com.yutel.multher.reaper.task.QueueTask;

public class ReaperServer<T extends TaskData> {
	private static final Logger log = LoggerFactory
			.getLogger(ReaperServer.class);
	private ServerType serverType;
	private QueueList<T> queueList;
	private OnDataListener<T> onDataListener;
	private OnTaskListener<T> onTaskListener;
	private OnAutoListener<T> onAutoListener;
	private int taskCount;
	private int taskInterval;
	private int queueMin;
	private int queueMax;
	private int queueInterval;
	private ThreadPoolExecutor executor;

	public ReaperServer() {
	}

	public void start() throws ReaperException {
		if (serverType == ServerType.QUEUE) {
			if (onDataListener == null) {
				throw new ReaperException("OnDataListener is not implement");
			}
			if (onTaskListener == null) {
				throw new ReaperException("OnTaskListener is not implement");
			}
			executor = (ThreadPoolExecutor) Executors
					.newFixedThreadPool(taskCount + 1);
			queueList = new QueueList<T>(queueMax);
			executor.execute(new QueueTask<T>(this));
			for (int i = 0; i < taskCount; i++) {
				executor.execute(new ParallelTask<T>(this));
			}
			onTaskListener = null;
			onDataListener = null;
		} else {// auto load data and process data
			if (onAutoListener == null) {
				throw new ReaperException("OnAutoListener is not implement");
			}
			executor = (ThreadPoolExecutor) Executors
					.newFixedThreadPool(taskCount);
			for (int i = 0; i < taskCount; i++) {
				executor.execute(new AutarkicTask<T>(this));
			}
			onAutoListener = null;
		}

	}

	public void shotdown() {
		log.info("shotdown()");
		executor.shutdown();
	}

	public ServerType getServerType() {
		return serverType;
	}

	public void setServerType(ServerType serverType) {
		this.serverType = serverType;
	}

	public OnDataListener<T> getOnDataListener() {
		return onDataListener;
	}

	public void setOnDataListener(OnDataListener<T> onDataListener) {
		this.onDataListener = onDataListener;
	}

	public OnTaskListener<T> getOnTaskListener() {
		return onTaskListener;
	}

	public void setOnTaskListener(OnTaskListener<T> onTaskListener) {
		this.onTaskListener = onTaskListener;
	}

	public OnAutoListener<T> getOnAutoListener() {
		return onAutoListener;
	}

	public void setOnAutoListener(OnAutoListener<T> onAutoListener) {
		this.onAutoListener = onAutoListener;
	}

	public int getTaskCount() {
		return taskCount;
	}

	public void setTaskCount(int taskCount) {
		this.taskCount = taskCount;
	}

	public int getTaskInterval() {
		return taskInterval;
	}

	public void setTaskInterval(int taskInterval) {
		this.taskInterval = taskInterval;
	}

	public int getQueueMin() {
		return queueMin;
	}

	public void setQueueMin(int queueMin) {
		this.queueMin = queueMin;
	}

	public int getQueueMax() {
		return queueMax;
	}

	public void setQueueMax(int queueMax) {
		this.queueMax = queueMax;
	}

	public int getQueueInterval() {
		return queueInterval;
	}

	public void setQueueInterval(int queueInterval) {
		this.queueInterval = queueInterval;
	}

	public QueueList<T> getQueueList() {
		return queueList;
	}

	public void setQueueList(QueueList<T> queueList) {
		this.queueList = queueList;
	}

}
